#include "t_i2c_m.h"


/**
 * @brief   Destroy I2C handle.
 * @param  me: I2C handle.
 * @retval None.
 */
void t_i2c_destroy(t_i2c_t *me)
{
    if (me != T_NULL) {
        T_FREE(me);
    }
}

/**
 * @brief   Create I2C handle.
 * @param  arg: User define parameter.
 * @param  cfgout_func: Change I/O out function.
 * @param  cfgin_func: Change I/O in function.
 * @param  delay_func: I2C delay times function.
 * @param  i2c_w_func: The gpio write function.
 * @param  i2c_r_func: The gpio read function.
 * @param  hw_gpio: Gpio i2c structures@t_i2c_t.
 * @retval I2C handle, NULL if failed.
 */
t_i2c_t *t_i2c_create(void *arg,
                     Ti2c_pincfg_func cfgout_func,
                     Ti2c_pincfg_func cfgin_func,
                     Ti2c_delay_func delay_func,
                     Ti2c_write_func i2c_w_func,
                     Ti2c_read_func i2c_r_func,
                     const t_i2c_gpio_t *hw_gpio)
{
    if (cfgout_func == T_NULL || cfgin_func == T_NULL || 
        delay_func == T_NULL || i2c_w_func == T_NULL || 
        i2c_r_func == T_NULL || hw_gpio == T_NULL) {
        return T_NULL;
    }

    t_i2c_t *me = (t_i2c_t *)T_MALLOC(sizeof(t_i2c_t));
    if (me == T_NULL) {
        return T_NULL;
    }

    me->arg = arg;
    me->delay_func = delay_func;
    me->hwcfgIn_func = cfgin_func;
    me->hwcfgOut_func = cfgout_func;
    me->write_func = i2c_w_func;
    me->read_func = i2c_r_func;
    me->hw_gpio = hw_gpio;
    // 初始化GPIO状态
    me->hwcfgOut_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl);
    me->hwcfgOut_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);
    
    // 初始状态：SCL和SDA都拉高
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_SET);

    return me;
}
/**
 * @brief   Set I2C device address.
 * @param  me: I2C handle.
 * @param  addr: 7-bit device address (will be shifted left by 1 internally).
 * @retval None.
 */
void t_i2c_setDev_addr(t_i2c_t *me, uint8_t dev_addr)
{
    if (me == T_NULL)
        return;

    me->dev_addr = dev_addr & 0x7F; // 保证是7位地址
}
/**
 * @brief   I2C start signal.
 * @param  me: I2C handle.
 * @retval None.
 */
void t_i2c_start(t_i2c_t *me)
{
    if (me == T_NULL || me->write_func == T_NULL || me->delay_func == T_NULL) {
        return;
    }

    // SDA和SCL初始状态都应该是高电平
    me->hwcfgOut_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_SET);
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);

    // 产生START条件：SCL高时，SDA从高变低
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_RESET);
    me->delay_func(i2c_delay_time);
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    me->delay_func(i2c_delay_time);
}

/**
 * @brief   I2C stop signal.
 * @param  me: I2C handle.
 * @retval None.
 */
void t_i2c_stop(t_i2c_t *me)
{
    if (!me) return;

    // SDA 配置为输出
    me->hwcfgOut_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);

    // 拉低 SDA（必须），等待至少 5us
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_RESET);
    me->delay_func(i2c_delay_time);

    // 拉高 SCL，等待至少 5us
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);

    // SDA 在 SCL 为高期间拉高（形成 STOP 条件）
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);
}

/**
 * @brief   I2C ack signal.
 * @param  me: I2C handle.
 * @retval None.
 */
void t_i2c_ack(t_i2c_t *me)
{
    if (me == T_NULL || me->delay_func == T_NULL || me->write_func == T_NULL) {
        return;
    }

    me->hwcfgOut_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);
    
    // SCL低时设置SDA为低(ACK)
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_RESET);
    me->delay_func(i2c_delay_time);
    
    // 产生时钟脉冲
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    me->delay_func(i2c_delay_time);
    
    // 释放SDA线
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_SET);
}

/**
 * @brief   I2C nack signal.
 * @param  me: I2C handle.
 * @retval None.
 */
void t_i2c_nack(t_i2c_t *me)
{
    if (me == T_NULL || me->delay_func == T_NULL || me->write_func == T_NULL) {
        return;
    }

    me->hwcfgOut_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);
    
    // SCL低时设置SDA为高(NACK)
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);
    
    // 产生时钟脉冲
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    me->delay_func(i2c_delay_time);
}

/**
 * @brief   I2C wait ack signal.
 * @param  me: I2C handle.
 * @retval 0: ack signal, 1: nack signal or error.
 */
uint8_t t_i2c_wait_ack(t_i2c_t *me)
{
    uint8_t waittime = 10;
    uint8_t ack = 1; // 默认返回NACK
    
    if (me == T_NULL || me->delay_func == T_NULL || 
        me->write_func == T_NULL || me->read_func == T_NULL) {
        return 1;
    }

    // SCL低时释放SDA线
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    me->hwcfgIn_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);
    
    // 产生时钟脉冲
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
    me->delay_func(i2c_delay_time);
    
    // 等待SDA被从设备拉低(ACK)
    while ((me->read_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda) == 1) && (waittime > 0)) {
        waittime--;
        me->delay_func(i2c_delay_time);
    }
    
    if (waittime > 0 && me->read_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda) == 0) {
        ack = 0; // 收到ACK
    }
    
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    me->delay_func(i2c_delay_time);
    
    return ack;
}

/**
 * @brief   I2C send byte.
 * @param  me: I2C handle.
 * @param  byte: The data to be sent.
 * @retval None.
 */
void t_i2c_send_byte(t_i2c_t *me, uint8_t byte)
{
    uint8_t i = 0;
    
    if (me == T_NULL || me->delay_func == T_NULL || me->write_func == T_NULL) {
        return;
    }

    me->hwcfgOut_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);
    me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
    
    for (i = 0; i < 8; i++) {
        // 设置数据位
        me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, (byte & 0x80) ? T_I2C_PIN_SET : T_I2C_PIN_RESET);
        me->delay_func(i2c_delay_time);
        
        // 产生时钟脉冲
        me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
        me->delay_func(i2c_delay_time);
        me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
        me->delay_func(i2c_delay_time);
        
        byte <<= 1;
    }
}

/**
 * @brief   I2C read byte.
 * @param  me: I2C handle.
 * @param  ack: 1 - send ACK after reading, 0 - send NACK.
 * @retval The data read.
 */
uint8_t t_i2c_read_byte(t_i2c_t *me, uint8_t ack)
{
    uint8_t i, dat = 0;

    if (me == T_NULL || me->delay_func == T_NULL || 
        me->write_func == T_NULL || me->read_func == T_NULL) {
        return 0;
    }

    me->hwcfgIn_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda);
    me->write_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda, T_I2C_PIN_SET); // 释放SDA
    
    for (i = 0; i < 8; i++) {
        me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
        me->delay_func(i2c_delay_time);
        
        // 产生时钟脉冲
        me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_SET);
        me->delay_func(i2c_delay_time);
        
        dat <<= 1;
        if (me->read_func(me->hw_gpio->sda_port, me->hw_gpio->pin_sda)) {
            dat |= 1;
        }
        
        me->write_func(me->hw_gpio->scl_port, me->hw_gpio->pin_scl, T_I2C_PIN_RESET);
        me->delay_func(i2c_delay_time);
    }

    // 发送ACK/NACK
    if (ack) {
        t_i2c_ack(me);
    } else {
        t_i2c_nack(me);
    }

    return dat;
}

/**
 * @brief   I2C write data to device.
 * @param  me: I2C handle.
 * @param  reg_addr: Register address.
 * @param  data: Data to write.
 * @retval 0: success, non-zero: error code.
 */
uint8_t t_i2c_write(t_i2c_t *me, uint8_t reg_addr, uint8_t data)
{
    if (me == T_NULL) {
        return I2C_ERR_NULL_PTR;
    }

    t_i2c_start(me);

    // 发送器件写地址
    t_i2c_send_byte(me, me->dev_addr<<1|0); // 清除最低位表示写
    if (t_i2c_wait_ack(me)) {
        t_i2c_stop(me);
        return I2C_ERR_NO_ACK;
    }

    // 发送寄存器地址
    t_i2c_send_byte(me, reg_addr);
    if (t_i2c_wait_ack(me)) {
        t_i2c_stop(me);
        return I2C_ERR_NO_ACK;
    }

    // 发送数据
    t_i2c_send_byte(me, data);
    if (t_i2c_wait_ack(me)) {
        t_i2c_stop(me);
        return I2C_ERR_NO_ACK;
    }

    t_i2c_stop(me);
    return I2C_OK;
}

/**
 * @brief   I2C read data from device.
 * @param  me: I2C handle.
 * @param  reg_addr: Register address.
 * @param  revdata: Pointer to store read data.
 * @retval 0: success, non-zero: error code.
 */
uint8_t t_i2c_read(t_i2c_t *me, uint8_t reg_addr, uint8_t *revdata)
{
    if (me == T_NULL || revdata == T_NULL) {
        return I2C_ERR_NULL_PTR;
    }

    t_i2c_start(me);

    // 发送器件写地址(先写寄存器地址)
    t_i2c_send_byte(me, me->dev_addr<<1|0x00); // w op
    if (t_i2c_wait_ack(me)) {
        t_i2c_stop(me);
        return I2C_ERR_NO_ACK;
    }

    // 发送寄存器地址
    t_i2c_send_byte(me, reg_addr);
    if (t_i2c_wait_ack(me)) {
        t_i2c_stop(me);
        return I2C_ERR_NO_ACK;
    }

    // 发送 RESTART 信号
    t_i2c_start(me);

    // 发送器件读地址
    t_i2c_send_byte(me, me->dev_addr | 0x01); // r op
    if (t_i2c_wait_ack(me)) {
        t_i2c_stop(me);
        return I2C_ERR_NO_ACK;
    }

    // 接收数据(发送NACK表示只读一个字节)
    *revdata = t_i2c_read_byte(me, 0);

    t_i2c_stop(me);
    return I2C_OK;
}
